{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Simply importing the needed classes.\n",
    "Notice the AAAx and BBBx dicts are optimal guesses for a few Q curves as interpolated from our CDS bootstrapping class\n",
    "This computation is expensive and does not always converge for our intial guess of x0Vas so I have copied them here to save some computations.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from pandas import DataFrame\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "from datetime import date\n",
    "import math\n",
    "from dateutil.relativedelta import relativedelta\n",
    "from random import shuffle\n",
    "import random\n",
    "import fractions\n",
    "\n",
    "AAAx={'3M': [1.0015824271136229, 0.07118430651357378, -0.16068883479216692, 0.0073983085859183105, 3.1083459253964976, -4.971784090683851, -0.4774848528659512, -0.10058722679096088, -0.32595880089361595, 1.2498165670968577, 3.4947594489126534, 0.7693240320536217, 1.3561952580367567, 6.371501575362355, 1.5717830330107334, 3.0431872392927932], '6M': [0.6253740242837578, 0.07187788235360676, 0.002756754524306165, 0.0007534565001362353, -1.9788331302293565, 1.3633887485139464, 5.119926963331688, 3.1051517704782445, 0.7634682512381973, -0.2440315461962444, -1.625294304111004, 1.1807892914373608, 1.5803472042649411, 2.2546258881657137, -0.6220529111275982, -3.918280795179225], '1Y': [0.02268430209412819, 0.12335315163831377, 0.0019492996048123179, 0.001628657655447479, 2.012129584631548, -0.14425637029306565, 3.0201995002610156, 2.147972541679386, -0.5128642176120338, 2.2747902950169627, -0.20546619851504466, 1.5945520333717365, 1.1372771020777144, 3.5153776822797216, 0.9602982736891876, -2.470770239032655], '3Y': [26.4868013103451, 0.10123386920113561, 0.007172027822595987, -0.0011729920248976869, 4.671838150691669, 2.0943942967130518, 1.8784163354679428, 2.829205309274365, 0.6419078923238758, 1.9913439793507237, 0.9155288227819725, 0.2038138762167537, 5.345533516522538, 3.7619427230742546, 0.1152302416309914, 2.657152673978014]}\n",
    "BBBx={'3M': [2.2676030271568077, 0.06869592728485677, -0.002415215219504258, 0.0010910153202821262, 2.076053981582788, -2.4830012835412374, 1.4792817746843325, 2.227857983492404, -0.3936126755070518, -0.16392645500488395, 1.285584627035015, 3.041436386446073, 3.2291187114730233, 3.3449348319234886, -2.054285553987237, 0.906769966943711]}\n",
    "class MC_Vasicek_Sim(object):\n",
    "    \"\"\" Monte Carlo simulator for interest rates under the Vasicek \n",
    "    model.\n",
    "\n",
    "    Attributes\n",
    "    ----------\n",
    "    kappa (float): Vasicek perameter: 'speed of reversion'.\n",
    "    theta (float): Vasicek perameter: 'long term mean level'.\n",
    "    sigma (float): Vasicek perameter: 'volatility'\n",
    "    r0 (float): Vasicek perameter: 'initial value'.\n",
    "    t_step (float): The time difference between the 'steps' in the \n",
    "        simulation. Represents 'dt' in the Vasicek model. Should always\n",
    "        be set to 1 day.\n",
    "    simNumber (int): The number of times the simulation is to execute.\n",
    "    datelist (list): A list of strings that are date-formatted (e.g.\n",
    "        '2016-10-17').\n",
    "    datelistlong (list): A list of days between (and including) \n",
    "        min(datelist) and max(datelist). Each element is of type \n",
    "        datetime.date.\n",
    "    ntimes (list):  The length of datelistlong.\n",
    "    libor (pandas DataFrame): A (1 + ntimes, simNumber) shaped array \n",
    "        that  contains the simulated discount curves. The zeroth column \n",
    "        contains the mean curve. The type of each element is \n",
    "        numpy.float64. The row labels are dates corresponding to\n",
    "        nodes in the simulation.\n",
    "    smallLibor (pandas DataFrame): A matrix subset of the \n",
    "        libor array. But it only contains rows corresponding to the \n",
    "        dates in `datelist` instead of `datelistlong`.\n",
    "    liborAvg (numpy ndarray): A vector containing the mean\n",
    "        simulated libor values. It is also the zeroth column of \n",
    "        `libor`.\n",
    "    \"\"\"\n",
    "    def __init__(self, datelist,x, simNumber,t_step):\n",
    "\n",
    "        \"\"\"Perameters\n",
    "        ----------\n",
    "        datelist (list): A list of strimgs that are date-formatted,\n",
    "            e.g. '2012-04-16'.\n",
    "        x (tuple): A 4-tuple containing the Vasicek SDE perameters:\n",
    "            kappa, theta, sigma, r0.\n",
    "        simNumber (int): The number of simulations that is to be \n",
    "            executed.\n",
    "        \"\"\"\n",
    "    #SDE parameters - Vasicek SDE\n",
    "    # dr(t) = k(θ − r(t))dt + σdW(t)\n",
    "        self.kappa = x[0]\n",
    "        self.theta = x[1]\n",
    "        self.sigma = x[2]\n",
    "        self.r0 = x[3]\n",
    "        self.simNumber = simNumber\n",
    "        self.t_step = t_step\n",
    "    #internal representation of times series - integer multiples of t_step\n",
    "        self.datelist = datelist\n",
    "    #creation of a fine grid for Monte Carlo integration\n",
    "        #Create fine date grid for SDE integration\n",
    "        minDay = min(datelist)\n",
    "        maxDay = max(datelist)\n",
    "        self.datelistlong = pd.date_range(minDay, maxDay).tolist()\n",
    "        self.datelistlong = [x.date() for x in self.datelistlong]\n",
    "        self.ntimes = len(self.datelistlong)\n",
    "        self.libor=[]\n",
    "        self.smallLibor = []\n",
    "        self.liborAvg=pd.DataFrame()\n",
    "        \n",
    "    def getLibor(self):\n",
    "        \"\"\"Executes the simulations and returns the simulated libor curves.\n",
    "\n",
    "        Returns\n",
    "        -------\n",
    "        A large 2D pandoc DataFrame. Each column represents a simulated value of\n",
    "        the libor curve at a given point in time. Each row corresponds to a\n",
    "        date in `datelonglist`. The zeroth column contains the mean value of\n",
    "        the simulated libor curves. The row labels are the elements of \n",
    "        datelonglist.\n",
    "        \"\"\"\n",
    "\n",
    "        rd = np.random.standard_normal((self.ntimes,self.simNumber))   # array of numbers for the number of samples\n",
    "        r = np.zeros(np.shape(rd))\n",
    "        nrows = np.shape(rd)[0]\n",
    "        sigmaDT = self.sigma* np.sqrt(self.t_step)\n",
    "        #calculate r(t)\n",
    "        r[1,:] = self.r0+r[1,:]\n",
    "        for i in np.arange(2,nrows):\n",
    "            r[i,:] = r[i-1,:]+ self.kappa*(self.theta-r[i-1,:])*self.t_step + sigmaDT*rd[i,:]\n",
    "        #calculate integral(r(s)ds)\n",
    "        integralR = r.cumsum(axis=0)*self.t_step\n",
    "        #calculate Libor\n",
    "        self.libor = np.exp(-integralR)\n",
    "        self.liborAvg=np.average(self.libor,axis=1)\n",
    "        self.libor=np.c_[self.liborAvg,self.libor]\n",
    "        self.libor = pd.DataFrame(self.libor,index=self.datelistlong)\n",
    "        return self.libor"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "genUnderlyings generates a stripped down version of an underlying with the important information stored in a tuple.\n",
    "The computation later gets very slow the larger the number of underlyings. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def genUnderlyings(notional,R,start,freq,quality,number):\n",
    "    out=[]\n",
    "    for i in range(0,number):\n",
    "        out.append((notional,start,freq,quality,R))\n",
    "    \n",
    "    return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class Scheduler(object):\n",
    "    def __init__(self):\n",
    "        pass\n",
    "    def extractDelay(self, freq):\n",
    "        if type(freq) == list:\n",
    "            freq = freq[0]\n",
    "        if (freq == 'Date'): return relativedelta(days=+ 1)\n",
    "        x = self.only_numerics(freq)\n",
    "        if (x == ''):\n",
    "            freqValue = 100\n",
    "        else:\n",
    "            freqValue = np.int(x)\n",
    "        if (freq.upper().find('D') != -1): delta = relativedelta(days=+  freqValue)\n",
    "        if (freq.upper().find('W') != -1): delta = relativedelta(weeks=+  freqValue)\n",
    "        if (freq.find('M') != -1): delta = relativedelta(months=+ freqValue)\n",
    "        if (freq.find('Y') != -1): delta = relativedelta(years=+ freqValue)\n",
    "        if (freq.find('ZERO') != -1): delta = relativedelta(years=+ freqValue)\n",
    "        return delta\n",
    "    def only_numerics(self, seq):\n",
    "        seq_type = type(seq)\n",
    "        return seq_type().join(filter(seq_type.isdigit, seq))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "The book calls this type of function an exact function. The underlying principle is that we can build the conditional loss distribution by remembering the fact that when the underlying credits are independent we have a natural recursive algorithim to calculate. Also notice, that for base cases if 0 credits default in a portfolio of 0 then the probability of this event is set to 1. In a portfolio of 0 credits and the probability of more than 1 default occuring is 0. \n",
    "Naturally, the probability that the portfolio survives is simply the multiplication of the underlying survival probabilities. So the rest is easily computed by recursion. \n",
    "\n",
    "In this function we used our Monte Carlo simulator to give us the Q(0,Maturity) for each of the underlyings. Then \n",
    "f(k,j) calculates the probability of k defaults in a portfolio of j credits under our homogenous loss. Although this is very easily extendable to inhomogenous cases as the book points out using a greatest common denomenator. \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class ExactFunc(object):\n",
    "    \n",
    "    def __init__(self,start,underlyings):\n",
    "        \n",
    "        myScheduler=Scheduler()\n",
    "        myDelays=[]\n",
    "        freqs=['3M','6M','1Y','3Y']\n",
    "        for i in range(0,len(freqs)):\n",
    "            myDelays.append(myScheduler.extractDelay(freqs[i]))\n",
    "        AAA={}\n",
    "        for i in range(0,len(freqs)):\n",
    "            vas=MC_Vasicek_Sim(x=AAAx[freqs[i]],datelist=[start,myDelays[i]+start],t_step=1/365.,simNumber=500)\n",
    "            AAA[freqs[i]]=vas.getLibor()[0].loc[myDelays[i]+start]\n",
    "        \n",
    "        BBB={'3M': MC_Vasicek_Sim(x=BBBx[freqs[0]],datelist=[start,myDelays[0]+start],t_step=1/365.,simNumber=500).getLibor()[0].loc[myDelays[0]+start]}\n",
    "        self.probs={'AAA': AAA, 'BBB':BBB}\n",
    "        self.underlyings=underlyings\n",
    "        \n",
    "    def f(self,k,j):\n",
    "        ''' \n",
    "        The recursion relation for the homogenous portfolio \n",
    "        takes in k: an int for numer of defaults \n",
    "        and j: number of underlyings you want to consider in the calculation k cannnot be greater than j\n",
    "        \n",
    "        \n",
    "        \n",
    "        '''\n",
    "        if(j==0 and k==0):\n",
    "            return 1\n",
    "        if(j==0 and k>0):\n",
    "            return 0\n",
    "        if(k==0 and j>0):\n",
    "            return self.f(k,j-1)*self.probs[self.underlyings[j][3]][self.underlyings[j][2]]\n",
    "        else:\n",
    "            return self.f(k,j-1)*(self.probs[self.underlyings[j][3]][self.underlyings[j][2]])+self.f(k-1,j-1)*(1-self.probs[self.underlyings[j][3]][self.underlyings[j][2]])\n",
    "    '''\n",
    "    Helper functions \n",
    "    \n",
    "    '''\n",
    "    def gcd(self,x, y):\n",
    "        while y != 0:\n",
    "            (x, y) = (y, x % y)\n",
    "        return x\n",
    "        \n",
    "    def totalGCD(self):\n",
    "        g=(1-self.underlyings[0][4])*self.underlyings[0][0]\n",
    "        for i in range(1,len(self.underlyings)):\n",
    "            g=self.gcd(g,((1-self.underlyings[i][4])*self.underlyings[i][0]))\n",
    "        return g\n",
    "\n",
    "    def getLossVec(self):\n",
    "        g=self.totalGCD()\n",
    "        n=[]\n",
    "        for i in range(0,len(self.underlyings)):\n",
    "            n.append(((1-self.underlyings[i][4])*self.underlyings[i][0])/g)\n",
    "        return n\n",
    "    \n",
    "    def fprime(self,k,j,vec):\n",
    "        '''\n",
    "        recursion relation for inhomogenous portfolio takes \n",
    "        k an int representing number of defaulted credits\n",
    "        j an int representing number of underlyings we wish to consider\n",
    "        vec a list of length of underlyings with the underlyings Loss given default scaled by gcd so\n",
    "        each entry is an int\n",
    "        '''\n",
    "        if(j==0 and k==0):\n",
    "            return 1\n",
    "        if(j==0 and k>0):\n",
    "            return 0\n",
    "        if(0<k and vec[j]>k):\n",
    "            return self.fprime(k,j-1,vec)*self.probs[self.underlyings[j][3]][self.underlyings[j][2]]\n",
    "        if(vec[j]<= k and k<=np.array(vec[0:j]).sum()):\n",
    "            return self.fprime(k,j-1,vec)*(self.probs[self.underlyings[j][3]][self.underlyings[j][2]])+self.fprime(k-vec[j],j-1,vec)*(1-self.probs[self.underlyings[j][3]][self.underlyings[j][2]])\n",
    "        else:\n",
    "            return self.fprime(k,j-1,vec)*self.probs[self.underlyings[j][3]][self.underlyings[j][2]]\n",
    "'''\n",
    "methods to get number of defaults required to break tranche upperstrike not used just informative\n",
    "\n",
    "\n",
    "\n",
    "'''\n",
    "    def getTrancheNumb(self,K):\n",
    "        sum=np.array(self.getLossVec()).sum()\n",
    "        losses=self.getLossVec()\n",
    "        totalLoss=0\n",
    "        for i in range(0,len(losses)):\n",
    "            totalLoss=totalLoss+losses[i]/sum\n",
    "            if(totalLoss >= K):\n",
    "                return i\n",
    "\n",
    "    def threshold(self,K):\n",
    "        sum=np.array(self.getLossVec()).sum()\n",
    "        return math.floor(sum*K)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "trim_start=date(2005,1,10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "credits=genUnderlyings(1,.4,trim_start,'3M','AAA',10)+genUnderlyings(1,.4,trim_start,'6M','AAA',10)+genUnderlyings(1,.4,trim_start,'1Y','AAA',10)+genUnderlyings(1,.4,trim_start,'3Y','AAA',5)+genUnderlyings(1,.4,trim_start,'3M','BBB',5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "ex=ExactFunc(underlyings=credits,start=trim_start)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "y=[]\n",
    "x=[]\n",
    "for i in range(0,7):\n",
    "    y.append(ex.f(i,len(ex.underlyings)-1))\n",
    "    x.append(i*.6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Container object of 7 artists>"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nyf8DMReX00ijbR8AAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x10976c860>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "plt.xlabel(\"Portfolio Loss %\")\n",
    "plt.ylabel(\"Probability\")\n",
    "plt.bar(x,y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here we are inserting a list of underlyings with a random recovery. After some expirementation the random recovery\n",
    "can cause the sum of the losses of the credits to get extremely large. There is a discussion in the book about this issue. So we consider only a minimal case where a few credits have recovery different than .4. But now we will look at the loss in terms of \"loss units.\" We create a method to determine the number of units lost out of the total will breach the upper strike. So we can limit our iterations of defaults to just these numbers. \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "randR=genUnderlyings(100,.4,trim_start,'3M','AAA',20)+genUnderlyings(100,.4,trim_start,'6M','AAA',10)+genUnderlyings(100,.4,trim_start,'1Y','AAA',10)+genUnderlyings(100,round(random.uniform(.25,.5),2),trim_start,'3Y','AAA',1)+genUnderlyings(100,.3,trim_start,'3M','BBB',1)\n",
    "shuffle(randR)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "exactRandR=ExactFunc(underlyings=randR,start=trim_start)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "z=[]\n",
    "w=[]\n",
    "for i in range(0,exactRandR.threshold(.1)):\n",
    "    z.append(exactRandR.fprime(i,len(exactRandR.underlyings)-1,exactRandR.getLossVec()))\n",
    "    w.append(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Container object of 253 artists>"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nvaraMmtZHpOQpEXa32MS84ZEkldU1UeS/Bdgn4ZV9Y45Pjb4+UOA62gOXH8PuAI4o6p2dLT/a+BT\nHriWpOWxvyGx0HDTvdt/5z3NtUtV7U1yFrCV5iD5BVW1I8mm5u3aPPsjS1mPJKkfi7rieiW5JyFJ\ni9frnkSSd8/3flW9bqkrliStfgsNN115QKqQJK1KDjdJ0hjre7jpnVX1hiSfYu6zm05b6oolSavf\nQsNNF7X//re+C5EkrT5DDzclOQw4gWaP4rqqurPPwuZYv8NNkrRIfV8nMbOS5wMfAL5Fc2X0I5Ns\nqqrPLHXFkqTVb9jbcuwEXlBV32ynHw38fVWd0HN9gzW4JyFJi3SgbhX+k5mAaH2b5iZ/kqQxttDZ\nTTNPifvnJJ8G/pbmmMRv0jxASJI0xhY6JvHCgde3As9oX/8AOKKXiiRJq4YX00nSGDtQZzcdDvwu\n8ETg8Jn5VfWflrpiSdLqN+yB64uAtTRPqvsnmifVeeBaksbcsKfAbq+qpyS5pqpOTPJrwOVVtb7/\nEn9Zg8NNkrRIB+oU2D3tvz9K8iTgaOAhS12pJGk0DHVMAtic5P7AW4AtNE+qe0tvVUmSVgXPbpKk\nMXZAhpuSPDDJe5JcleTKJO9M8sClrlSSNBqGPSZxMfB94CXAS4EfAh/rqyhJ0uow7NlNX6+qJ82a\nd21VPbm3yvatweEmSVqkA3V209YkG5Osab9eBnxuqSuVJI2GefckkvyE5oZ+Ae4N3N2+tQb4aVUd\n1XuF99TinoQkLVKvexJVdd+qOqr9d01VHdp+rRk2IJJMJtmZZFeSs+d4/7QkX0uyPckVSZ621M5I\nkpbXYh5fehrw6+3kdFX93RCfWQPsAk4Fbqa5vfjGqto50ObIqvpZ+/rJwN9W1ePnWJZ7EpK0SAfq\nFNjzgNcD32i/Xp/k7UN8dB2wu6qur6o9NGdJbRhsMBMQrftwz5CWJGmFDXvF9fOAk6rqboAkFwLb\ngTct8LljgBsGpm+kCY5fkeR04O3Ag4HnD1mTJKlnw4YEwP2A29rXRy9nEVV1KXBpklOAtwHP6mo7\nNTUFwMTEBBMTE8tZhiSNvOnpaaanp5dtecNeJ3EGcB7wBZoznX4dOKeq5r2gLsl6YKqqJtvpc4Cq\nqvPn+cy3gKdW1W2z5ntMQpIWaX+PSSwYEklC8/yIu4CntrOvqKpbhijuEOA6mgPX3wOuAM6oqh0D\n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\nyZCQJHX6/0y9wzrz5XR7AAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1177d14e0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "plt.xlabel(\"Portfolio Loss In Dollars\")\n",
    "plt.ylabel(\"Probability\")\n",
    "plt.bar(w,z)"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3.0
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}